﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace I3.AgenteIA.Dominio.Gramatica
{
    public class ElementoInterpreter : IElementoInterpreter
    {
        /// <summary>
        /// Armazena o repositorio de acesso aos dados da gramatica
        /// </summary>
        private IRepositorioGramatica _repositorioGramatica;


        /// <summary>
        /// Construtor protected da factory dos elementos
        /// </summary>
        protected ElementoInterpreter() { }

        /// <summary>
        /// Construtor padrão da factory dos elementos
        /// </summary>
        public ElementoInterpreter(IRepositorioGramatica repositorioGramatica)
        {
            _repositorioGramatica = repositorioGramatica;
        }

        /// <summary>
        /// Cria a instancia dos elementos individuais da sentenca
        /// </summary>
        /// <param name="sentenca">Sentenca com o texto que deverá ser separadao</param>
        public IEnumerable<Elemento> Interpretar(Sentenca sentenca)
        {

            List<Elemento> retorno = new List<Elemento>();
            
            // Separa a sentenca em elementos unicos considerando o caracter
            // de espaço como parametro durante a separação e analisa cada um
            // dos elementos encontratos
            string[] elementosCandidatos = sentenca.Texto.Split(' ');
            foreach (string elemento in elementosCandidatos)
            {
                List<string> parcial = new List<string>();

                // Separa o elemento em um array de caracteres
                List<char> arrayElemento = new List<char>(elemento.ToArray());

                // recupera as posições candidata para separação
                int[] posicoesCandidatas = this.ObterPosicaoSeparadores(arrayElemento.ToArray());

                // analisa as posições candidatas encontradas
                for (int i = 0, total = posicoesCandidatas.Length; i < total; i++)
                {
                    int indexAtual = posicoesCandidatas[i];

                    // Separa o candidato se a posição dele for a ultima
                    // posição do elemento.
                    if ((indexAtual + 1) == (arrayElemento.Count()))
                    {
                        parcial.Insert(0, elemento.Substring(indexAtual, 1));
                        arrayElemento[(indexAtual)] = ' ';
                    }

                    // Separa o candidato se o proximo elemento também for 
                    // um elemento candidato.
                    else if ( posicoesCandidatas.Contains((indexAtual + 1)) )
                    {
                        parcial.Insert(0, elemento.Substring(indexAtual, 1));
                        arrayElemento[(indexAtual)] = ' ';
                    }
                }

                string ultimaParte = (new String(arrayElemento.ToArray())).Trim();
                if (!String.IsNullOrEmpty(ultimaParte))
                {
                    parcial.Insert(0, ultimaParte);
                }

                foreach (string item in parcial)
                {
                    if (!String.IsNullOrEmpty(item.Trim()))
                        retorno.Add(new Elemento(item));
                }
            }

            return retorno;
        }

        /// <summary>
        /// Recupera o posicionamento dos caracteres finalizadores do elemento
        /// </summary>
        private int[] ObterPosicaoSeparadores(char[] caracteres)
        {
            List<int> separadores = new List<int>();

            for (int caracterAtual = 0; caracterAtual < caracteres.Count(); caracterAtual++)
            {
                // Se o caractere não for um caractere alfanumerico, insere o na 
                // lista de separadores candidatos.
                if (!char.IsLetterOrDigit(caracteres[caracterAtual]))
                    separadores.Add(caracterAtual);
            }

            return separadores.ToArray();
        }
    }
}
